#include "classsemantic.h"
#include "visitordata.h"

void ClassSemantic::fillInheritance(SemanticVisitorData * data)
{
  const std::vector<InheritanceNode *> & vector=m_class->inherits()->vector();
  if (!(m_class->inherits()))
  {
	  m_inheritance.insert(std::make_pair<std::string,InheritanceSemantic>("ANY",InheritanceSemantic()));
	  return ;
  }
  if (m_is_interface)
  {
		removeAnyFromInterface();
  }
  //If Vector is empty add ANY as a superclass
  if (vector.size()==0)
  {
	  m_inheritance.insert(std::make_pair<std::string,InheritanceSemantic>("ANY",InheritanceSemantic()));
	  return ;
  }
  for (unsigned int i=0;i<vector.size();i++)
  {
	if (data->isCorrect(vector[i]->className(),false))
	{
		std::string ancestorname=vector[i]->className()->fullName();
		if (m_inheritance.find(ancestorname)==m_inheritance.end())
			m_inheritance.insert(std::make_pair<std::string,InheritanceSemantic>(ancestorname,InheritanceSemantic()));
		InheritanceSemantic & filling=m_inheritance[ancestorname];
		for (unsigned int j=0;j<vector[i]->redefinesCount();j++)
		{
			if (! (filling.addRedefine(vector[i]->redefine(j))))
				data->add(new DuplicateRedefinition(vector[i]->redefines()->vector()[j],
				                                    vector[i]->redefine(j)));
		}
		for (unsigned int j=0;j<vector[i]->renameCount();j++)
		{
			std::string alias;
			if (vector[i]->renameAlias(j))
				alias=*(vector[i]->renameAlias(j));
			if (! (filling.addRename(vector[i]->renameOldName(j),
				                     vector[i]->renameNewName(j),
									 alias)))
			{
				data->add(new DuplicateRename(vector[i]->renames()->vector()[j],
					                          vector[i]->renameOldName(j)
											 ));
			}
		}

	}
  }
  
}


void ClassSemantic::checkInterface(SemanticVisitorData * data)
{
	m_is_interface=m_fields.size()==0 && m_class->type()==CLM_DEFERRED;
	bool hasAbstract=false;
	for (std::map<std::string,Method>::iterator it=m_methods.begin();
		(it!=m_methods.end());
		it++)
	{
		int decltype=it->second.m_type;
		if ((decltype & FDT_ABSTRACT) == 0)
			m_is_interface=false;
		else
		{
			hasAbstract=true;
		}
		if (it->second.m_overriden_methods.size()!=0)
		{
			m_is_interface=false;
		}
	}
	int mytype=m_class->type();
	if (mytype==CLM_FROZEN && hasAbstract)
	{
		data->add(new AbstractFrozenClass(m_class));
	}
	if (mytype!=CLM_DEFERRED && hasAbstract)
	{
		data->add(new ImplicitAbstractClass(m_class));
	}

	if (m_is_interface)
		removeAnyFromInterface();
}
void ClassSemantic::removeAnyFromInterface()
{
	if (m_inheritance.find("ANY")!=m_inheritance.end())
		m_inheritance.erase("ANY");
}
void ClassSemantic::checkFMI(SemanticVisitorData * data)
{
  bool hasEffective=false;
  bool miherror=false;
  bool fiherror=false;

  for (std::map<std::string,InheritanceSemantic>::iterator it=m_inheritance.begin();
	   it!=m_inheritance.end();
	   it++)
  {
	   ClassSemantic * sem=NULL;
	   if (data->getClassByName(it->first,sem))
	   {
		  if (sem->isInterface())
		  {
			  it->second.setImplements();
		  }
		  else
		  {
			  if (hasEffective)
				  miherror=true;
			  hasEffective=true;
		  }
		  if (sem->cnode()->type()==CLM_FROZEN)
			  fiherror=true;
	   }
		
  }
  /*! Interfaces can have multiple inheritance
   */
  //if (miherror==false && isInterface() && m_inheritance.size()>1)
  //	  miherror=true;

  if (miherror)
	  data->add(new MultipleInheritance(m_class));
  if (fiherror)
	  data->add(new FrozenInherited(m_class));
}